package com.gitee.wsl.func.predicate

import com.gitee.wsl.func.InvokeCall

typealias IntPredicate = Predicate<Int>
typealias LongPredicate = Predicate<Long>
typealias CharPredicate =  Predicate<Char>

/**
 * Represents a predicate (boolean-valued function) of one argument.
 *
 *
 * This is a [functional interface](package-summary.html)
 * whose functional method is [.test].
 *
 * @param <T> the type of the input to the predicate
 *
 * @since 1.8
</T> */
fun interface Predicate<T>: InvokeCall<T, Boolean> {
    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return `true` if the input argument matches the predicate,
     * otherwise `false`
     */
    fun test(t: T): Boolean

    fun accept(t: T): Boolean = test(t)

    override fun invoke(t: T): Boolean = test(t)

    /**
     * Returns a composed predicate that represents a short-circuiting logical
     * AND of this predicate and another.  When evaluating the composed
     * predicate, if this predicate is `false`, then the `other`
     * predicate is not evaluated.
     *
     *
     * Any exceptions thrown during evaluation of either predicate are relayed
     * to the caller; if evaluation of this predicate throws an exception, the
     * `other` predicate will not be evaluated.
     *
     * @param other a predicate that will be logically-ANDed with this
     * predicate
     * @return a composed predicate that represents the short-circuiting logical
     * AND of this predicate and the `other` predicate
     * @throws NullPointerException if other is null
     */
    infix fun and(other: Predicate<in T>): Predicate<T> {
        return Predicate { t: T -> test(t) && other.test(t) }
    }

    /**
     * Returns a predicate that represents the logical negation of this
     * predicate.
     *
     * @return a predicate that represents the logical negation of this
     * predicate
     */
    fun negate(): Predicate<T> {
        return Predicate { t: T -> !test(t) }
    }

    /**
     * Returns a composed predicate that represents a short-circuiting logical
     * OR of this predicate and another.  When evaluating the composed
     * predicate, if this predicate is `true`, then the `other`
     * predicate is not evaluated.
     *
     *
     * Any exceptions thrown during evaluation of either predicate are relayed
     * to the caller; if evaluation of this predicate throws an exception, the
     * `other` predicate will not be evaluated.
     *
     * @param other a predicate that will be logically-ORed with this
     * predicate
     * @return a composed predicate that represents the short-circuiting logical
     * OR of this predicate and the `other` predicate
     * @throws NullPointerException if other is null
     */
    infix fun or(other: Predicate<in T>): Predicate<T> {
        return Predicate { t: T -> test(t) || other.test(t) }
    }

    companion object {


        /**
         * Returns a predicate that is the negation of the supplied predicate.
         * This is accomplished by returning result of the calling
         * `target.negate()`.
         *
         * @param <T>     the type of arguments to the specified predicate
         * @param target  predicate to negate
         *
         * @return a predicate that negates the results of the supplied
         * predicate
         *
         * @throws NullPointerException if target is null
         *
         * @since 11
        </T> */
        fun <T> not(target: Predicate<in T>): Predicate<in T> {
            return target.negate()
        }
    }
}